import hmac
import json
import requests
import hashlib
import sys
import time
import base64

from coin.exchange.base.kr_rest.auth_base import AuthKey
from coin2.api_client.common import (SyncQueryer)
from enum import Enum

class OrderType(Enum):
  BUY = "buy"
  SELL = "sell"

class OrderMethod(Enum):
  LIMIT = "limit"
  MARKET = "market"
  STOP_LIMIT = "stoplimit"
  STOP_MARKET = "stopmarket"

class BtcturkAuth(requests.auth.AuthBase):
  def __init__(self, key):
    self._key = AuthKey.from_file(key)

  def _gen_signature(self, nonce: str, api_key: str):
    assert nonce, "nonce must be not None and not empty!"
    assert api_key, "api_key must be not None and not empty!"

    before_signature = ''.join([api_key, nonce]).encode()
    secret = base64.b64decode(self._key.secret_key)

    signature = hmac.new(secret, before_signature, digestmod=hashlib.sha256)
    return base64.b64encode(signature.digest())

  def __call__(self, req: requests.PreparedRequest):
    # https://docs.btcturk.com/authentication/authentication-v1
    nonce = str(int(time.time() * 1000))

    req.headers.update({'X-PCK': self._key.access_key})
    req.headers.update({'X-Stamp': nonce})

    signature = self._gen_signature(nonce, self._key.access_key)
    req.headers.update({'X-Signature': signature})
    req.prepare_headers(req.headers)

    return req

class BtcturkPrivateClient():
  def __init__(self, key_path: str, ip=None, proxies = None):
    self._auth = BtcturkAuth(key_path)
    self._url = "https://api.btcturk.com"

    self._query = SyncQueryer(api_host=self._url, auth=self._auth, ip=ip, proxies=proxies)

  def get_open_order(self, pair_symbol: str = None):
    method = "GET"
    params = {
      'pairSymbol': pair_symbol,
    }
    path = "/api/v1/openOrders"

    response = self._query.query(method=method, path=path, params=params)
    return response.json()

  def cancel_order(self, id: str):
    assert id, "id must be not None and not empty!"

    method = "DELETE"
    params = {
      'id': id,
    }
    path = "/api/v1/order"

    response = self._query.query(method=method, path=path, params=params)
    return response.json()

  def submit_order(
    self,
    order_type: OrderType,
    order_method: OrderMethod,
    pair_symbol: str,
    quantity: str,
    price: str,
    stop_price: str = None,
    new_order_client_id: str = None,
):
    assert order_type, "order_type must be not None!"
    assert order_method, "order_method must be not None!"
    assert pair_symbol, "pair_symbol must be not None and not empty!"
    assert quantity, "quantity must be not None and not empty!"
    assert price, "price must be not None and not empty!"

    method = "POST"
    json = {
      'orderType': order_type.value,
      'orderMethod': order_method.value,
      'pairSymbol': pair_symbol,
      'quantity': quantity,
      'price': price,
      'stopPrice': stop_price,
      'newOrderClientId': new_order_client_id,
    }
    path = "/api/v1/order"

    response = self._query.query(method=method, path=path, json=json)
    return response.json()

if __name__ == "__main__":
  key_path = sys.argv[1]
  proxies={
    'http': 'http://proxy_upbit_accounting:1bdgeFqbWw1Wg0grcZ@52.78.142.159:31280',
    'https': 'http://proxy_upbit_accounting:1bdgeFqbWw1Wg0grcZ@52.78.142.159:31280',
  }
  
  btcturk = BtcturkPrivateClient(key_path, proxies=proxies)
  info = btcturk.get_open_order()
  # info = btcturk.cancel_order("12347354976")
  # info = btcturk.submit_order(OrderType.SELL, OrderMethod.LIMIT, "BTCTRY", "0.0001", "1000000")
  print(json.dumps(info, indent=2))
